#ifndef __WIZ_MEMORY_ALLOCATOR_BASE_HPP__SHANHAOBO_19800429__
#define __WIZ_MEMORY_ALLOCATOR_BASE_HPP__SHANHAOBO_19800429__

#include "../../../Base/WizBase.hpp"
#include "../../Container/WizDataTypeMap.hpp"

namespace Wiz
{
    namespace Memory
    {
        namespace Allocator
        {
            namespace Base
            {
                struct RecordInfo
                {
                    ::Wiz::Size::Type       m_Size;
                    ::Wiz::String::Type     m_File;
                    ::Wiz::Int::Type        m_Line;
                    ::Wiz::String::Type     m_Func;

                    RecordInfo(
                        ::Wiz::Size::In     InSZ,
                        ::Wiz::String::In   InFL,
                        ::Wiz::Int::In      InLN,
                        ::Wiz::String::In   InFN
                        ) : m_Size(InSZ), m_File(InFL), m_Line(InLN), m_Func(InFN)
                    {
                        
                    }
                };

                class MemoryAddressConflict : public ::Wiz::Exception::Type
                {
                    typedef ::Wiz::Exception::Type  tSuper;
                public:
                    MemoryAddressConflict() : tSuper("Memory Address Conflict!")
                    {}
                public:
                };

                class MemoryAddressError : public ::Wiz::Exception::Type
                {
                    typedef ::Wiz::Exception::Type  tSuper;
                public:
                    MemoryAddressError(
                        ::Wiz::Void::Ptr    InPtr,
                        ::Wiz::String::In   InFL,
                        ::Wiz::Int::In      InLN,
                        ::Wiz::String::In   InFN
                        ) : tSuper("Can not Find MemoryAddress!")
                        , m_Record(0, InFL, InLN, InFN)
                        , m_ThePtr(InPtr)
                    {}
                public:
                    RecordInfo          m_Record;
                    ::Wiz::Void::Ptr    m_ThePtr;
                };

                template<class DerivedT>
                class Type
                {
                public:

                    typedef DerivedT            tDerived;
                    typedef ::Wiz::Map::Type<::Wiz::Void::Ptr, RecordInfo> tMap;

                    static tMap     s_Map;
                    ///////////////////////////////////////////
                    /// With Debug Info
                    static ::Wiz::Void::Ptr AllocateWithDebugInfo(
                        ::Wiz::Size::In SZ,
                        ::Wiz::String::In FL,
                        ::Wiz::Int::In LN,
                        ::Wiz::String::In Func
                        )
                    {
                        ::Wiz::Void::Ptr MemPtr = tDerived::Allocate(SZ);
                        if (::Wiz::IsValidPtr(MemPtr))
                        {
                            if (s_Map.InsertUnique(MemPtr, RecordInfo(SZ, FL, LN, Func)))
                            {
                                return tDerived::Allocate(SZ);
                            }
                            else
                            {
                                tDerived::Deallocate(MemPtr);
                                MemPtr = WIZ_NULLPTR;
                                ::Wiz::Exception::Throw(MemoryAddressConflict());
                            }
                        }
                        return WIZ_NULLPTR;
                    }
                    static ::Wiz::Void::Ptr AllocateArrayWithDebugInfo(
                        ::Wiz::Size::In SZ,
                        ::Wiz::String::In FL,
                        ::Wiz::Int::In LN,
                        ::Wiz::String::In Func
                        )
                    {
                        ::Wiz::Void::Ptr MemPtr = tDerived::Allocate(SZ);
                        if (::Wiz::IsValidPtr(MemPtr))
                        {
                            if (s_Map.InsertUnique(MemPtr, RecordInfo(SZ, FL, LN, Func)))
                            {
                                return tDerived::AllocateArray(SZ);
                            }
                            else
                            {
                                tDerived::DeallocateArray(MemPtr);
                                MemPtr = WIZ_NULLPTR;
                                ::Wiz::Exception::Throw(MemoryAddressConflict());
                            }
                        }
                        return WIZ_NULLPTR;
                    }
                    /// With Debug Info
                    static ::Wiz::Void::Type DeallocateWithDebugInfo(
                        ::Wiz::Void::InOutPtr VPtr,
                        ::Wiz::String::In FL,
                        ::Wiz::Int::In LN,
                        ::Wiz::String::In Func
                        )
                    {
                        if (s_Map.Remove(VPtr))
                        {
                            tDerived::Deallocate(VPtr);
                        }
                        else
                        {
                            ::Wiz::Exception::Throw(
                                MemoryAddressError(VPtr, FL, LN, Func)
                                );
                        }
                    }
                    static ::Wiz::Void::Type DeallocateArrayWithDebugInfo(
                        ::Wiz::Void::InOutPtr VPtr,
                        ::Wiz::String::In FL,
                        ::Wiz::Int::In LN,
                        ::Wiz::String::In Func
                        )
                    {
                        if (s_Map.Remove(VPtr))
                        {
                            tDerived::DeallocateArray(VPtr);
                        }
                        else
                        {
                            ::Wiz::Exception::Throw(
                                MemoryAddressError(VPtr, FL, LN, Func)
                                );
                        }
                    }
                    ///////////////////////////////////////////
                };
            } /// end of namespace Base
        } /// end of namespace Allocator
    } /// end of namespace Memory
} /// end of namespace Wiz

#endif /*__WIZ_MEMORY_ALLOCATOR_BASE_HPP__SHANHAOBO_19800429__*/
